package com.norman.sorry.core.cards;

import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import java.util.Random;

/**
 * A helper class for creating a concrete version of a deck of cards.
 * 
 * @author Brian Norman
 * @version 0.0.1 beta
 * @since 0.0.1 beta
 */
public abstract class AbstractDeck implements IDeck {

   /**
    * The current ordering of cards.
    */
   protected List<? extends ICard>         deck;

   /**
    * The card drawer that gets the next card in the deck.
    */
   protected ListIterator<? extends ICard> iter;

   /**
    * The source of randomness for the shuffler.
    */
   protected Random                        rand;

   /**
    * Creates a new deck of cards with the initial list of cards. The deck is
    * shuffled before the cards are drawn.<br>
    * <br>
    * The reference to the list of cards should not be kept as the order of it
    * will change. Also, mutating the list while cause the iterator that draws
    * the cards to break.
    * 
    * @param deck
    *           the list of cards in this deck.
    */
   public AbstractDeck(List<? extends ICard> deck) {
      this.deck = deck;
      rand = new Random(System.currentTimeMillis());
      shuffle();
   }

   /**
    * {@inheritDoc}
    * 
    * @see com.norman.sorry.core.cards.IDeck#next()
    */
   @Override
   public ICard next() {
      if (!iter.hasNext()) {
         shuffle();
      }

      if (iter.hasNext()) {
         return iter.next();
      } else {
         return null;
      }
   }

   /**
    * {@inheritDoc}
    * 
    * @see com.norman.sorry.core.cards.IDeck#shuffle()
    */
   @Override
   public void shuffle() {
      Collections.shuffle(deck, rand);
      iter = deck.listIterator();
   }

}
